<?php

namespace Chaosyeo\SolarEngine\Event;

use Chaosyeo\SolarEngine\Arrayable;

class Event implements Arrayable
{
    const APP_TYPE_MP  = 'mp';
    const APP_TYPE_APP ='app';
    const APP_TYPE_WEB ='web';

    // 预置事件
    const EVENT_NAME_PRESET_INSTALL = 'install';
    const EVENT_NAME_PRESET_START   = 'start';
    const EVENT_NAME_PRESET_END     = 'end';

    // 预定义事件名, 上报时需要拼合事件名前缀
    const EVENT_NAME_PREDEF_IMPRESSION_AD = 'imp';
    const EVNET_NAME_PREDEF_CLICK_AD      = 'click';
    const EVENT_NAME_PREDEF_PURCHASE      = 'pur';
    const EVENT_NAME_PREDEF_ORDER         = 'order';
    const EVENT_NAME_PREDEF_REGISTRATION  = 'reg';
    const EVENT_NAME_PREDEF_LOGIN         = 'login';
    const EVENT_NAME_PREDEF_ATTRIBUTION   = 'attr';

    // 数据源类型
    const SOURCE_TYPE = 'api';
    
    // 数据类型
    const TYPE = 'event';

    // PACKAGE_TYPE 枚举值
    const PACKAGE_TYPE_CHINESE = 1; // 数据存储区域中国大陆
    const PACKAGE_TYPE_OVERSEA = 2; // 数据存储区域海外

    protected $appkey;
    protected $eventName;
    protected $sourceType;
    protected $type;
    protected $eventId;
    protected $ts;
    protected $packageType;
    public $properties;
    protected $user;
    protected $appType;
    
    /**
     * @param int $packageType 数据存储区域（必传）
     * @param User $user 用户及设备信息（必传）
     * @param Properties $properties 事件属性（必传）
     * @param string $appType 应用类型（必传）
     * @param string $eventName 事件标识（如未设置默认值必传）
     * @param array $params 可选参数数组
     */
    public function __construct(int $packageType, User $user, Properties $properties, string $appType = self::APP_TYPE_APP, string $eventName = '', array $params = [])
    {
        if (!in_array($packageType, [self::PACKAGE_TYPE_CHINESE, self::PACKAGE_TYPE_OVERSEA])) {
            throw new \InvalidArgumentException('Invalid package type');
        }
        
        if (empty($appType) ||!in_array($appType, [self::APP_TYPE_MP, self::APP_TYPE_APP, self::APP_TYPE_WEB])) {
            throw new \InvalidArgumentException('Invalid app type');
        }

        if (empty($eventName) && empty($this->eventName)) {
            throw new \InvalidArgumentException('Event name is required');
        }

        if (!empty($eventName) && !preg_match('/^[a-zA-Z0-9_]+$/', $eventName)) {
            throw new \InvalidArgumentException('Invalid event name');
        }
    
        $this->packageType = $packageType;
        $this->user        = $user;
        $this->properties  = $properties;
        $this->appType     = $appType;
        $this->eventName   = $this->eventName ?? $eventName;
        $this->sourceType  = self::SOURCE_TYPE;
        $this->type        = self::TYPE;
      
        if (isset($params['eventId'])) {
            $this->eventId = $params['eventId'];
        }
    }
    public function getEventName(): string
    {
        if (in_array($this->eventName, [
            self::EVENT_NAME_PRESET_INSTALL,
            self::EVENT_NAME_PRESET_START,
            self::EVENT_NAME_PRESET_END,
            self::EVENT_NAME_PREDEF_IMPRESSION_AD,
            self::EVNET_NAME_PREDEF_CLICK_AD,
            self::EVENT_NAME_PREDEF_PURCHASE,
            self::EVENT_NAME_PREDEF_ORDER,
            self::EVENT_NAME_PREDEF_REGISTRATION,
            self::EVENT_NAME_PREDEF_LOGIN,
            self::EVENT_NAME_PREDEF_ATTRIBUTION
        ])) {
            return '_' . $this->appType . ucfirst($this->eventName);
        }
        return $this->eventName;
    }


    public function toArray(): array
    {
        $data = [];
        $vars = get_object_vars($this);
        array_walk($vars, function ($value, $key) use (&$data) {
            if (!is_null($value) && $key !== 'properties' && $key!== 'user' && $key !== 'appType' && $key !== 'eventName') {
                $key = '_' . strtolower(preg_replace('/([a-z])([A-Z])/', '$1_$2', $key));
                $data[$key] = $value;
            }
        });
        $data = array_merge($data, $this->user->toArray());

        $data['_event_name'] = $this->getEventName();
        $data['properties']  = $this->properties->toArray();
        return $data;
    }


}